package jbase.project.system.net.http.websearcher;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.URL;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jbase.project.system.core.common.Console;
import jbase.project.system.core.common.EventHook;
import jbase.project.system.exception.SysException;
import jbase.project.system.net.http.HttpURL;
import jbase.project.system.util.RegUtil;

public class WebSearcher implements Console {

	private TaskServiceProvider service;
	private EventHook hook;
	private Thread work;
	private volatile boolean isContinue = true;
	private volatile boolean isExit = false;

	public WebSearcher(EventHook hook, TaskServiceProvider service) {
		this.service = service;
		this.hook = hook;
	}

	public void start() {
		this.hook.event("webFinder.started", this);
		this.work = Thread.currentThread();
		while (!isExit) {
			while (this.isContinue) {
				String url = null;
				HttpClient httpClient = null;
				HttpResponse response = null;
				url = this.service.getNextURL();
				if (url == null) {
					/** 没有要处理的URL，结束，返回! */
					this.isContinue = false;
					this.isExit = true;
					Thread.currentThread().interrupt();
				} else {
					try {
						hook.event("with", url);
						httpClient = new HttpClient(url);
					} catch (SysException e) {
						this.hook.event("exception", e, "httpClient.new", url);
						this.service.errorURL(url);
						continue;
					}
					try {
						response = httpClient.doGetResponse();
					} catch (SysException e) {
						this.hook.event("exception", e, "httpClient.doGetResponse", url);
						this.service.errorURL(url);
						continue;
					}

					HttpURL urlx = null;
					try {
						urlx = new HttpURL(url);
						List<String> links = response.getLinks();
						List<String> images = response.getImgs();
						for (String link : links) {
							try {
								String href = findPropertyValue("href", link);
								href = buildFullURL(urlx, href);
								// 开始解子析逻辑--------------------------------------------
								if (this.service.isURLInTaskRange(href)) {
									if (!this.service.isExists(href)) {
										this.service.addURLToTasks(href);
									}
								}

								// 开始下载逻辑-----------------------------------------------
								if (this.service.isDownLoadSource(href)) {
									this.hook.event("DownloadSourceFound", href);
									this.service.save(href, new HttpClient(href).doGetResponse().getBody());
								}
							} catch (Exception e) {
								e.printStackTrace();
								hook.event("exception", e);
								this.service.errorURL(url);
							}
						}
						for (String img : images) {
							String href = findPropertyValue("SRC", img);
							href = buildFullURL(urlx, href);

							// 开始解子析逻辑--------------------------------------------
							// if (this.service.isURLInTaskRange(href)) {
							// if (!this.service.isExists(href)) {
							// this.service.addURLToTasks(href);
							// }
							// }

							// 开始下载逻辑-----------------------------------------------
							if (this.service.isDownLoadSource(href)) {
								this.hook.event("DownloadSourceFound", href);
								this.service.save(href, new HttpClient(href).doGetResponse().getBody());
							}
						}
						this.service.finishURL(url);
					} catch (Throwable e) {
						e.printStackTrace();
						hook.event("exception", e);
						service.errorURL(url);
					}
				}
			}
			/** 休眠线程 **/
			try {
				Thread.sleep(0);
			} catch (InterruptedException e) {

			}
		}
		hook.event("exit");
	}

	private String findPropertyValue(final String propName, final String tag) {
		final ResultValue resultValue = new ResultValue();
		Runnable run = new Runnable() {
			@Override
			public void run() {
				try {
					String reg = "[\\s\\r\\n]+";
					char[] chars = propName.toCharArray();
					for (char ch : chars) {
						reg += ("[" + new String(new char[] { ch }).toUpperCase()
								+ new String(new char[] { ch }).toLowerCase() + "]");
					}
					reg += "[\\s\\r\\n]*=[\\s\\r\\n]*(\\'|\\\")[^(\\'|\\\")]*(\\'|\\\")\\s*";
					Pattern pattern = Pattern.compile(reg);
					Matcher matcher = pattern.matcher(tag);
					while (matcher.find()) {
						String prop = matcher.group();
						resultValue.setValue(prop.split("=")[1].replace("\"", "").replace("'", "").replace(" ", ""));
						break;
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		Thread t = new Thread(run);
		t.setDaemon(true);
		t.start();
		try {
			t.join();
		} catch (InterruptedException e) {

		}
		// run.run();
		return (String) resultValue.getValue();
	}

	private String buildFullURL(HttpURL urlx, String href) {
		if (!isFullURL(href)) {
			String hostBase = urlx.getHostBase();
			String urlBase = urlx.getUrlBase();
			if (href.startsWith("/")) {
				href = hostBase.substring(0, hostBase.length() - 1) + href;
			} else {
				href = urlBase + href;
			}
		}
		return href;
	}

	private boolean isFullURL(String url) {
		boolean is = false;
		Pattern p = Pattern.compile(RegUtil.toRegxIC("HTTP") + "[Ss]?://[^/]+.*");
		Matcher m = p.matcher(url);
		if (m.matches()) {
			is = true;
		}
		return is;
	}

	private String findHostBase(String url) {
		String base = "";
		Pattern p = Pattern.compile(RegUtil.toRegxIC("HTTP") + "\\s?://[^/]+");
		Matcher m = p.matcher(url);
		if (m.find()) {
			base = m.group() + "/";
		}
		return base;
	}

	private void call(final String href) {
		Thread t = new Thread(new Runnable() {
			public void run() {
				hook.event("http.find.img", href);
			}
		});
		t.start();
	}

	@Override
	public <T, R> R executeCommand(String command, T... objects) {
		if (command.equals("exit")) {
			this.isExit = true;
			this.isContinue = false;
			this.work.interrupt();
		} else if (command.equals("pause")) {
			this.isContinue = false;
		} else if (command.equals("continue")) {
			this.isContinue = true;
			this.work.interrupt();
		}
		return (R) (Object) true;
	}

}
